package com.service.data.log4j.appender.rabbitmq

import com.rabbitmq.client.{Channel, Connection, ConnectionFactory}
import com.service.data.commons.utils.Preconditions
import org.apache.log4j.AppenderSkeleton
import org.apache.log4j.spi.LoggingEvent

import scala.beans.BeanProperty

/**
  * @author 伍鲜
  *
  *         Log4j Appender to RabbitMQ
  */
class RabbitMQAppender extends AppenderSkeleton {

  private var connection: Connection = _
  private var channel: Channel = _

  @BeanProperty var hostname: String = _
  @BeanProperty var username: String = _
  @BeanProperty var password: String = _
  @BeanProperty var port: Int = -1

  @BeanProperty var exchange: String = _
  @BeanProperty var routingKey: String = ""
  @BeanProperty var mandatory: Boolean = false
  @BeanProperty var immediate: Boolean = false

  /**
    * 初始化RabbitMQ连接
    */
  def init(): Unit = {
    hostname = Preconditions.checkNotNull(hostname, "Rabbit MQ hostname must be specified. For example: log4j.appender.rabbit.hostname=127.0.0.1")
    exchange = Preconditions.checkNotNull(exchange, "Rabbit MQ exchange must be specified. For example: log4j.appender.rabbit.exchange=wux.exchange")

    val factory = new ConnectionFactory

    factory.setHost(hostname)
    if (username != null) factory.setUsername(username)
    if (password != null) factory.setPassword(password)
    if (port != -1) factory.setPort(port)

    connection = factory.newConnection
    channel = connection.createChannel
  }

  /**
    * 日志追加
    *
    * @param loggingEvent
    */
  override def append(loggingEvent: LoggingEvent): Unit = {
    if (channel == null) {
      RabbitMQAppender.synchronized({
        if (channel == null) {
          init()
        }
      })
    }
    channel.basicPublish(exchange, routingKey, mandatory, immediate, null, getLayout.format(loggingEvent).getBytes())
  }

  override def close(): Unit = {
    channel.close()
    connection.close()
  }

  override def requiresLayout(): Boolean = true
}

object RabbitMQAppender {

}